const express = require('express');
const { ApolloServer } = require('apollo-server-express');
//导入数据限制
const depthLimit = require('graphql-depth-limit');
const { createComplexityLimitRule } = require('graphql-validation-complexity');
//提升安全性
const helmet = require('helmet');
//跨域资源共享
const cors = require('cors');
require('dotenv').config();

//导入本地模块
const db = require('./db');
const models = require('./models');
const typeDefs = require('./schema');
const resolvers = require('./resolvers');
const jwt = require('jsonwebtoken')

//在.env文件指定的端口或4000端口上运行服务器
const port = process.env.PORT || 4000;
//把DB_HOST值存入一个变量
const DB_HOST = process.env.DB_HOST;

const app = express();
app.use(helmet());
app.use(cors());

//链接数据库
db.connect(DB_HOST);

const getUser = token => {
    if (token) {
        try{
            return jwt.verify(token, process.env.JWT_SECRET)
        }catch(err){
            throw new Error('Session invalid');
        }
    }
}

//设置Apollo Server
const server = new ApolloServer({ 
    typeDefs,
    resolvers,
    validationRules: [depthLimit(5), createComplexityLimitRule(1000)],
    context: async ({ req }) => {
        //从首部中获取令牌
        const token = req.headers.authorization;
        //尝试使用令牌检索用户
        const user = getUser(token);
        //把数据库模型添加到上下文中
        return{ models, user };
    } 
});

//应用Apollo GraphQL中间件，把路径设为/api
server.applyMiddleware({ app, path:'/api' });

app.listen(port,()=>
    console.log(
        `GraphQL Server running at http://localhost:${port}${server.graphqlPath}`
    )
);